package com.chase.passwordmaster.mine.export

import android.content.Context
import android.content.Intent
import android.os.AsyncTask
import android.os.Bundle
import android.os.Environment
import android.view.View
import android.widget.EditText
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.ViewModelProviders
import com.chase.passwordmaster.R
import com.chase.passwordmaster.data.AccountViewModel
import com.chase.passwordmaster.entity.DecryptedAccount
import com.chase.passwordmaster.utils.*
import requireWriteAndReadPermission
import java.io.File

class ExportActivity : AppCompatActivity() {
    companion object {
        const val DIR = "PasswordMaster"
        const val EXPORT_DIR = "$DIR/export"
        const val EXPORT_CLEARTEXT_FILE_NAME = "export.json"
        const val EXPORT_ENCRYPTED_FILE_NAME = "export_encrypted.json"

        fun actionStart(context: Context) {
            val intent = Intent(context, ExportActivity::class.java)
            context.startActivity(intent)
        }
    }

    private lateinit var accountViewModel: AccountViewModel

    private lateinit var cpBack: View
    private lateinit var cpExportCleartext: View
    private lateinit var cpExportRSA: View
    private lateinit var cpPublicKey: EditText

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_export)

        accountViewModel = ViewModelProviders.of(this).get(AccountViewModel::class.java)

        cpBack = findViewById(R.id.back_export)
        cpExportCleartext = findViewById(R.id.export_cleartext_export)
        cpExportRSA = findViewById(R.id.export_rsa_export)
        cpPublicKey = findViewById(R.id.public_key_export)

        useDarkStatusBar()
        useImmersingNavigator()

        initCPBack()
        initCPExportCleartext()
        initCPExportRSA()
    }

    private fun initCPBack() {
        cpBack.setOnClickListener { onBackPressed() }
    }

    private fun initCPExportCleartext() {
        cpExportCleartext.setOnClickListener {
            AlertDialog.Builder(this)
                .setTitle("导出的信息将不被加密\n请妥善保管，及时删除")
                .setNegativeButton("取消") { dialog, which ->
                    dialog.cancel()
                }
                .setPositiveButton("导出") { dialog, which ->
                    requireWriteAndReadPermission(this)

                    val externalAccountList = accountViewModel.getAccountLiveData().value?.map {
                        ExternalDecryptedAccount(it)
                    }

                    externalAccountList?.let {
                        ExportTask().execute(
                            ExportInfo(
                                dir = "${Environment.getExternalStorageDirectory().absolutePath}/$EXPORT_DIR",
                                fileName = EXPORT_CLEARTEXT_FILE_NAME,
                                content = it
                            )
                        )
                    } ?: showToast("导出失败")
                }
                .show()
        }
    }

    private fun initCPExportRSA() {
        // Encrypted account by given rsa
        fun encryptedExternalAccountByRSA(account: DecryptedAccount, publicKeyString: String) =
            account.run {
                ExternalDecryptedAccount(
                    website,
                    encryptByRSA(username, publicKeyString),
                    encryptByRSA(password, publicKeyString),
                    name?.let { encryptByRSA(it, publicKeyString) },
                    tel?.let { encryptByRSA(it, publicKeyString) },
                    qq?.let { encryptByRSA(it, publicKeyString) },
                    weChat?.let { encryptByRSA(it, publicKeyString) },
                    email?.let { encryptByRSA(it, publicKeyString) },
                    memo
                )
            }

        cpExportRSA.setOnClickListener {
            // Check RSA public key
            val publicKeyString = cpPublicKey.text.toString()
            if (!isValidPublicKey(publicKeyString)) {
                showToast("RSA 公钥不合法")
                return@setOnClickListener
            }

            // Alert dialog
            AlertDialog.Builder(this)
                .setTitle("加密导出")
                .setNegativeButton("取消") { dialog, which ->
                    dialog.cancel()
                }
                .setPositiveButton("导出") { dialog, which ->
                    // Require write and read permission
                    requireWriteAndReadPermission(this)

                    // Encrypted
                    val encryptedList = accountViewModel.getAccountLiveData().value
                        ?.map { encryptedExternalAccountByRSA(it, publicKeyString) }

                    // Write out
                    encryptedList?.let {
                        ExportTask().execute(
                            ExportInfo(
                                dir = "${Environment.getExternalStorageDirectory().absolutePath}/$EXPORT_DIR",
                                fileName = EXPORT_ENCRYPTED_FILE_NAME,
                                content = it
                            )
                        )
                    } ?: showToast("导出失败")
                }
                .show()
        }
    }

    data class ExportInfo(
        val dir: String,
        val fileName: String,
        val content: Any
    )

    inner class ExportTask : AsyncTask<ExportInfo, Int, Boolean>() {

        private var exportInfo: ExportInfo? = null

        override fun doInBackground(vararg params: ExportInfo?): Boolean {
            params[0]?.let {
                exportInfo = it
                export(it.dir, it.fileName, it.content)
                return true
            }
            return false
        }

        override fun onPostExecute(result: Boolean?) {
            result?.run {
                if (this) {
                    exportInfo?.run { showToast("已导出至\n$dir/$fileName", Toast.LENGTH_LONG) }
                        ?: run { showToast("已导出") }
                } else {
                    showToast("导出失败")
                }
            } ?: showToast("导出失败")
        }
    }
}

/**
 * Remove exported files
 */
fun removeExportedFiles() {
    val encryptedFile = File("${Environment.getExternalStorageDirectory().absolutePath}/${ExportActivity.EXPORT_DIR}/${ExportActivity.EXPORT_ENCRYPTED_FILE_NAME}")
    val cleartextFile = File("${Environment.getExternalStorageDirectory().absolutePath}/${ExportActivity.EXPORT_DIR}/${ExportActivity.EXPORT_CLEARTEXT_FILE_NAME}")

    if (encryptedFile.exists()) {
        encryptedFile.delete()
    }

    if (cleartextFile.exists()) {
        cleartextFile.delete()
    }
}